package BehaviorPattern.Visitor;

/**
 * @author: Themberfue
 * @date: 2025/8/14 10:51
 * @description:
 */
import java.util.ArrayList;
import java.util.List;

// 1. 抽象访问者：定义对各类商品的操作接口
interface Visitor {
    void visit(Book book);          // 访问书籍
    void visit(Electronic electronic);  // 访问电子产品
    void visit(Clothing clothing);    // 访问服装
}

// 2. 具体访问者1：计算总价
class PriceCalculator implements Visitor {
    private double totalPrice = 0;

    @Override
    public void visit(Book book) {
        // 书籍有折扣：原价*0.9
        double price = book.getPrice() * 0.9;
        totalPrice += price;
        System.out.println("书籍《" + book.getName() + "》：原价" + book.getPrice() + "，折后" + price);
    }

    @Override
    public void visit(Electronic electronic) {
        // 电子产品加税费：原价*1.1
        double price = electronic.getPrice() * 1.1;
        totalPrice += price;
        System.out.println("电子产品" + electronic.getName() + "：原价" + electronic.getPrice() + "，含税价" + price);
    }

    @Override
    public void visit(Clothing clothing) {
        // 服装按原价计算
        totalPrice += clothing.getPrice();
        System.out.println("服装" + clothing.getName() + "：" + clothing.getPrice());
    }

    // 获取总价
    public double getTotalPrice() {
        return totalPrice;
    }
}

// 2. 具体访问者2：生成发票
class InvoiceGenerator implements Visitor {
    private StringBuilder invoice = new StringBuilder();

    @Override
    public void visit(Book book) {
        invoice.append("• 书籍：").append(book.getName())
                .append(" (ISBN: ").append(book.getIsbn()).append(") - ")
                .append(book.getPrice()).append("元\n");
    }

    @Override
    public void visit(Electronic electronic) {
        invoice.append("• 电子产品：").append(electronic.getName())
                .append(" (保修：").append(electronic.getWarrantyPeriod()).append("个月) - ")
                .append(electronic.getPrice()).append("元\n");
    }

    @Override
    public void visit(Clothing clothing) {
        invoice.append("• 服装：").append(clothing.getName())
                .append(" (尺码：").append(clothing.getSize()).append(") - ")
                .append(clothing.getPrice()).append("元\n");
    }

    // 获取发票内容
    public String getInvoice() {
        return "===== 购物发票 =====\n" + invoice.toString() + "===================";
    }
}

// 3. 抽象元素：商品
interface Product {
    void accept(Visitor visitor);  // 接受访问者
    String getName();
    double getPrice();
}

// 4. 具体元素1：书籍
class Book implements Product {
    private String name;
    private double price;
    private String isbn;

    public Book(String name, double price, String isbn) {
        this.name = name;
        this.price = price;
        this.isbn = isbn;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);  // 接受访问者，并调用访问者的对应方法
    }

    public String getIsbn() {
        return isbn;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public double getPrice() {
        return price;
    }
}

// 4. 具体元素2：电子产品
class Electronic implements Product {
    private String name;
    private double price;
    private int warrantyPeriod;  // 保修期限（月）

    public Electronic(String name, double price, int warrantyPeriod) {
        this.name = name;
        this.price = price;
        this.warrantyPeriod = warrantyPeriod;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);  // 接受访问者
    }

    public int getWarrantyPeriod() {
        return warrantyPeriod;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public double getPrice() {
        return price;
    }
}

// 4. 具体元素3：服装
class Clothing implements Product {
    private String name;
    private double price;
    private String size;

    public Clothing(String name, double price, String size) {
        this.name = name;
        this.price = price;
        this.size = size;
    }

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);  // 接受访问者
    }

    public String getSize() {
        return size;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public double getPrice() {
        return price;
    }
}

// 5. 对象结构：购物车
class ShoppingCart {
    private List<Product> products = new ArrayList<>();

    // 添加商品
    public void addProduct(Product product) {
        products.add(product);
    }

    // 移除商品
    public void removeProduct(Product product) {
        products.remove(product);
    }

    // 让访问者访问所有商品
    public void accept(Visitor visitor) {
        for (Product product : products) {
            product.accept(visitor);
        }
    }
}

// 6. 客户端代码
public class VisitorExample {
    public static void main(String[] args) {
        // 创建商品
        Product book = new Book("设计模式详解", 89.0, "9787111641247");
        Product laptop = new Electronic("笔记本电脑", 5999.0, 24);
        Product shirt = new Clothing("纯棉衬衫", 199.0, "L");

        // 创建购物车并添加商品
        ShoppingCart cart = new ShoppingCart();
        cart.addProduct(book);
        cart.addProduct(laptop);
        cart.addProduct(shirt);

        // 1. 使用价格计算器访问者计算总价
        System.out.println("=== 计算商品价格 ===");
        PriceCalculator priceVisitor = new PriceCalculator();
        cart.accept(priceVisitor);  // 让访问者访问所有商品
        System.out.println("总价：" + priceVisitor.getTotalPrice() + "元\n");

        // 2. 使用发票生成器访问者生成发票
        System.out.println("=== 生成购物发票 ===");
        InvoiceGenerator invoiceVisitor = new InvoiceGenerator();
        cart.accept(invoiceVisitor);  // 让访问者访问所有商品
        System.out.println(invoiceVisitor.getInvoice());
    }
}

